﻿using ManagementApi.Mvc;
using ManagementApi.Mvc.ApplicationContexts;
using Modules;
using Modules.Person;
using Modules.Project;
using Modules.Project.Entitys;
using Modules.System.User;
using Pipelines.Sockets.Unofficial.Arenas;
using PmSoft;
using PmSoft.Entity;
using PmSoft.Exceptions;

namespace ManagementApi.Authorizers
{
    /// <summary>
    /// 验证人员银行卡数据权限
    /// </summary>
    [UseDI(ServiceLifetime.Scoped)]
    public class PersonBankOwnAuthorizer
    {
        private readonly PersonBankService personBankService;
        private readonly PersonService personService;
        private readonly ProjectGroupMemberService projectGroupMemberService;
        private readonly ProjectService projectService;
        private readonly ProjectUserApplicationContext applicationContext;

        /// <summary>
        /// 验证人员银行卡数据权限
        /// </summary>
        /// <param name="personBankService"></param>
        /// <param name="personService"></param>
        /// <param name="projectGroupMemberService"></param>
        /// <param name="applicationContext"></param>
        /// <param name="projectService"></param>
        public PersonBankOwnAuthorizer(PersonBankService personBankService, PersonService personService, ProjectGroupMemberService projectGroupMemberService, ProjectUserApplicationContext applicationContext, ProjectService projectService)
        {
            this.personBankService = personBankService;
            this.personService = personService;
            this.projectGroupMemberService = projectGroupMemberService;
            this.projectService = projectService;
            this.applicationContext = applicationContext;
        }

        /// <summary>
        /// 检查并抛出数据权限验证失败信息
        /// </summary>
        /// <param name="personBankId"></param>
        /// <exception cref="OwnAuthorizationFailedException"></exception>
        public void CheckAndThrowIfOwnAuthenticationFailed(int personBankId)
        {
            var personBank = personBankService.GetPersonBank(personBankId) ?? throw new BusinessException("数据不存在");
            PersonInfo personInfo = personService.GetPersonByCardNo(personBank.IdCard) ?? throw new BusinessException("人员信息不存在");
            IEnumerable<ProjectGroupMember> members = projectGroupMemberService.GetProjectGroupMembersByPersonId(personInfo.PersonId);
            var projects = projectService.GetProjectInfos(members.Select(i => i.ProjectId));
            var user = applicationContext.CurrentUser;

            if (user is DeptUser deptUser)
            {
                if (!projects.Any(i => i.IndustryType == deptUser.IndustryType))
                    throw new OwnAuthorizationFailedException();
            }
            if (user is IProjectUser)
            {
                if (!projects.Any(i => i.ProjectId == applicationContext.CurrentProjectInfo.ProjectId))
                {
                    throw new OwnAuthorizationFailedException();
                }
            }
        }

        /// <summary>
        /// 检查并抛出数据权限验证失败信息
        /// </summary>
        /// <param name="personBankIds"></param>
        public void CheckAndThrowIfOwnAuthenticationFailed(IEnumerable<int> personBankIds)
        {
            foreach (int personBankId in personBankIds)
            {
                CheckAndThrowIfOwnAuthenticationFailed(personBankId);
            }
        }
    }
}